import { Asset, AssetManager, assetManager, Prefab, SpriteAtlas, SpriteFrame } from "cc";
import { ViewId } from "../../modules_common/view/IView";



export class ResMgr {

    private _bundles: Map<string, AssetManager.Bundle> = new Map();

    private _bundleMapViewId: Map<AssetManager.Bundle, Set<ViewId>> = new Map();

    /**
     * 加载bundle
     * @param viewId 
     * @param name 
     * @returns 
     */
    async loadBundle(viewId: ViewId, name: string): Promise<AssetManager.Bundle> {
        const bundle = this._bundles.get(name);
        if (bundle) {
            return Promise.resolve(bundle);
        }
        return new Promise((resolve, reject) => {
            assetManager.loadBundle(name, (err, bundle) => {
                if (err) {
                    return reject(err);
                }

                /** */
                let ss = this._bundleMapViewId.get(bundle);
                if (!ss) {
                    ss = this._bundleMapViewId.set(bundle, new Set()).get(bundle)
                }
                ss.add(viewId);

                /** */
                this._bundles.set(name, bundle);

                resolve(bundle);
            });
        });
    }

    private _singlePicResMapViewId: Map<string, Set<ViewId>> = new Map();
    private _singlePicRes: Map<string, SpriteFrame> = new Map();

    /**
     * 加载散图
     * @param bundleName 
     * @param res 
     */
    async loadSinglePicResByBundle(viewId: number, bundleName: string, resName: string): Promise<SpriteFrame> {
        const bundle = this._bundles.get(bundleName);
        if (!bundle) {
            return Promise.reject(`bundle not found, bundle name .. ` + bundleName)
        }

        const keyName = `${bundleName}#${resName}`
        const res = this._singlePicRes.get(keyName)
        if (res) {
            return Promise.resolve(res);
        }

        return new Promise((resolve, reject) => {
            bundle.load(resName, SpriteFrame, (err, data: SpriteFrame) => {
                if (err) {
                    return reject(err);
                }
                /** */
                let ss = this._singlePicResMapViewId.get(keyName);
                if (!ss) {
                    ss = this._singlePicResMapViewId.set(keyName, new Set()).get(keyName);
                }
                ss.add(viewId);
                /** */
                this._singlePicRes.set(keyName, data);

                resolve(data);
            })
        })
    }

    private _atlasMapViewId: Map<string, Set<ViewId>> = new Map();
    private _atlas: Map<string, SpriteAtlas> = new Map();

    /**
     * 加载图集
     * @param viewId 
     * @param bundleName 
     * @param atlasName 
     * @param type 
     */
    private async loadAtlasByBundle(viewId: number, bundleName: string, atlasName: string): Promise<SpriteAtlas> {
        const bundle = this._bundles.get(bundleName);
        if (!bundle) {
            return Promise.reject(`bundle not found, bundle name .. ` + bundleName)
        }
        if (!atlasName) {
            return Promise.resolve(null)
        }
        const keyName = `${bundleName}#${atlasName}`;
        const res = this._atlas.get(keyName);
        if (res) {
            return Promise.resolve(res);
        }
        return new Promise((resolve, reject) => {
            bundle.load(atlasName, SpriteAtlas, (err, data: SpriteAtlas) => {
                if (err) {
                    return reject(err);
                }
                /** */
                let ss = this._atlasMapViewId.get(keyName);
                if (!ss) {
                    ss = this._atlasMapViewId.set(keyName, new Set()).get(keyName);
                }
                ss.add(viewId);
                /** */
                this._atlas.set(keyName, data);

                resolve(data);
            })
        })
    }

    async loadAtlasArrByBundle(viewId: number, bundleName: string, atlasNameArr: string[]): Promise<any> {
        const total = atlasNameArr.length;
        if (!total) {
            return Promise.resolve(null);
        }
        let count = 0;
        return new Promise((resolve, reject) => {
            for (const atlasName of atlasNameArr) {
                this.loadAtlasByBundle(viewId, bundleName, atlasName).then(() => {
                    count++;
                    if (count >= total) {
                        resolve(null);
                    }
                }).catch((reason)=>{
                    reject(reason);
                })
            }
        })

    }

    private _prefabMapViewId: Map<string, Set<ViewId>> = new Map();
    private _prefab: Map<string, Prefab> = new Map();

    /**
     * 加载预制体
     * @param viewId 
     * @param bundleName 
     * @param prefabPath 
     * @returns 
     */
    async loadPrefab(viewId: number, bundleName: string, prefabPath: string): Promise<Prefab> {
        const bundle = this._bundles.get(bundleName);
        if (!bundle) {
            return Promise.reject(`bundle not found, bundle name .. ` + bundleName)
        }
        const keyName = `${bundleName}#${prefabPath}`;
        const res = this._prefab.get(keyName);
        if (res) {
            return Promise.resolve(res);
        }
        return new Promise((resolve, reject) => {
            bundle.load(prefabPath, (err, data: Prefab) => {
                if (err) {
                    return reject(err);
                }
                /** */
                let ss = this._prefabMapViewId.get(keyName);
                if (!ss) {
                    ss = this._prefabMapViewId.set(keyName, new Set()).get(keyName);
                }
                ss.add(viewId);
                /** */
                this._prefab.set(keyName, data);

                resolve(data);
            })
        })

    }


}